package cn.com.lyj6851.sso.config;



import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import cn.com.lyj6851.common.properties.RootSecurityProperties;

/**
 * 认证服务器
 * @author Administrator
 *
 */

@Configuration
@EnableAuthorizationServer
public class SsoAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{

	@Autowired
	private RootSecurityProperties securityProperties;
	@Autowired 
	private TokenStore tokenStore;
	/**
     * 使用缓存存储token
     * 
     */
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;
    @Bean
    @ConditionalOnProperty(prefix = "micro.service.oauth2", name = "storeType", havingValue = "redis")
    public TokenStore redisTokenStore() {
        return new MyRedisTokenStore(redisConnectionFactory);
    }
    
    // matchIfMissing ：当tokenStore没有值的时候是否生效
    // 当tokenStore = jwt的时候或则tokenStore没有配置的时候使用下面的配置; 也就是默认使用jwt
    @Bean
    @ConditionalOnProperty(prefix = "micro.service.oauth2", name = "tokenStore", havingValue = "jwt", matchIfMissing = true)
    public TokenStore jwtTokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
    
	@Autowired
	public PasswordEncoder passwordEncoder;
	
	/**
	 * 给哪些应用发令牌
	 */
	@Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		/*InMemoryClientDetailsServiceBuilder inMemory = clients.inMemory();
		OAuth2ClientProperties[] clientsInCustom = securityProperties.getOauth2().getClients();
		for(OAuth2ClientProperties p : clientsInCustom) {
			
			inMemory.withClient(p.getClientId())
				    .secret(p.getClientSecret())
				    .authorizedGrantTypes("authorization_code", "refresh_token")
				    .accessTokenValiditySeconds(p.getAccessTokenValidateSeconds())
				    .scopes(p.getScopes())
				    .autoApprove(true);
		}
		log.info(Arrays.toString(clientsInCustom));*/
		clients.inMemory()
	        .withClient("myid1")
	        .secret(passwordEncoder.encode("myid1"))
	        .authorizedGrantTypes("authorization_code", "refresh_token")
	        .scopes("all","read","write")
	        .accessTokenValiditySeconds(3600)
	        .refreshTokenValiditySeconds(2592000) // 设置刷新令牌的过期时间
	        .autoApprove(true) //跳过认证确认的过程，设置autoApprove 为true
	        .and()
	        .withClient("myid2")
	        .secret(passwordEncoder.encode("myid2"))
	        .authorizedGrantTypes("authorization_code", "refresh_token")
	        .scopes("all","read","write")
	        .accessTokenValiditySeconds(3600)
	        .refreshTokenValiditySeconds(2592000)
	        .autoApprove(true);
    }
	
	
	@Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore)
                 //.tokenStore(jwtTokenStore()) //或使用用本地存储token
                 .accessTokenConverter(jwtAccessTokenConverter());
    }

	
	
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        // 客户端来向认证服务器获取签名的时候需要登录认证身份才能获取
        // 因为客户端需要用密钥解密jwt字符串  NoOpPasswordEncoder.getInstance()
    	//security.passwordEncoder(NoOpPasswordEncoder.getInstance()); // 密码加密策略
        security.tokenKeyAccess("isAuthenticated()");
    }

	
	

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(securityProperties.getOauth2().getJwtSigningKey());
        return converter;
    }

	
	
}
